package com.yiwan.app.preventionsis.view;

import android.content.Context;
import android.graphics.*;
import android.os.AsyncTask;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import com.app.tianwan.tianwanframe.utils.LogUtil;
import com.yiwan.app.preventionsis.R;
import com.yiwan.app.preventionsis.util.ScreenResolution;

import java.util.ArrayList;
import java.util.List;

/**
 * ��ת̨
 */
public class RotateFlower extends View {

    /**
     * ����ͼƬ�ߴ�, ���ڼ�������
     */
    private final int Flower_Radius = 277;

    private int nYoffset = 0;
    private int nXoffset = 0;
    /**
     * ͼ�꣬����Ӧ��Activity�� ����
     */
    private List<FunctionIcon> fiList = new ArrayList<FunctionIcon>();
    /**
     * ��ת̨����ͼ
     */
    private Bitmap turntable;

    /**
     * ͼƬ��ʾ/ʵ�ʴ�С����
     */
    private float scale;

    private RotateTask rotateTask;

    // û���ͼ��
    private int[] resIcons = {R.drawable.prev_cheat,
            R.drawable.prev_fire, R.drawable.prev_rob,
            R.drawable.prev_steal, R.drawable.save_self, R.drawable.prev_terror_v2};
    // ����ʱ��ͼ��
    private static int[] res_Icons = {R.drawable.prev_cheat,
            R.drawable.prev_fire, R.drawable.prev_rob,
            R.drawable.prev_steal, R.drawable.save_self, R.drawable.prev_terror_v2};

    private static Context context;

    private Matrix matrix = new Matrix();
    private float[] matrixFloat = new float[9];

    private float density = isInEditMode() ? 320 : ScreenResolution.getDM().density;
    private int[] locationOnScreen = new int[2];

    /**
     * ����¼�����ӿ�
     */
    private OnClickListener onClickListener = null;

    @SuppressWarnings({"rawtypes"})

    private Paint paint; // ����
    private int mWidth = 0; // ���
    /**
     * ��Բ�İ뾶
     */
    private float arcRadius;
    /**
     * ͼ�� ��Բ�ĵľ���icon(left,top)
     */
    private float iconRadius;
    /**
     * �����Ƿ�����ת̨
     */
    private boolean touchInTurnTable; // Ԫ������
    /**
     * �����Ƿ������Ŀؼ�
     */
    private boolean touchInCenterAre; // Ԫ������
    /**
     * ��������ԭ�����ߺ�y��ļн�
     * move
     */
    private double touchDegreeFromX, _touchDegreeFromX;

    private double moveDegreeFromX;

    /**
     * ��ת�Ƕ�
     */
    private double turnDegree;
    /**
     * 60�Ƚ�
     */
    private final double Angle60Degree = Math.PI * 2 / resIcons.length; // Բ����/6

    public RotateFlower(Context context, AttributeSet attrs) {
        super(context, attrs);
        RotateFlower.context = context;
        releaseRes();
        paint = new Paint(Paint.ANTI_ALIAS_FLAG); //
        rotateTask = new RotateTask();
        rotateTask.execute();
        //Log.d("Init RotateFlower", "density = " + density);
    }

    @Override
    protected void onDetachedFromWindow() {
        if (rotateTask != null) {
            rotateTask.stop();
        }
        //Log.d("RotateFlower", "onDetachedFromWindow");
        super.onDetachedFromWindow();
    }

    /**
     * �ͷ��ڴ�
     */
    private void releaseRes() {
        if (turntable != null) {
            turntable.recycle();// �ͷ���Դ
            turntable = null;
        }
//        if (divider != null) {
//            divider.recycle();
//            divider = null;
//        }
        for (FunctionIcon fi : fiList) {
            if (fi.icon != null) {
                fi.icon.recycle();
                fi.icon = null;
            }
            if (fi._icon != null) {
                fi._icon.recycle();
                fi._icon = null;
            }
        }
    }

    // ��view�Ĵ�С����仯ʱ�������൱�ڳ�ʼ������
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        if (mWidth == 0) {
            rotateTask.pause();
            releaseRes();
            mWidth = w;
            scale = (float) mWidth / 2.0f / Flower_Radius;
//            LogUtil.d("scale = " + scale);
            scale = scale / density;
            Matrix m = new Matrix();
            m.setScale(scale, scale);
//            LogUtil.d("scale = " + scale + ", density = " + density + ", width = " + mWidth + ", Flower_Radius = " + Flower_Radius);
            Bitmap bTemp = BitmapFactory.decodeResource(getResources(),
                    R.drawable.heart);
//            turntable = BitmapCreate.bitmapFromResource(getResources(), R.drawable.heart, (int)((float)311 * scale), (int)((float)311 * scale));
            turntable = Bitmap.createBitmap(bTemp, 0, 0,
                    (int) (bTemp.getWidth()),
                    (int) (bTemp.getHeight()),
                    m, true);
            bTemp.recycle();
            LogUtil.d("turntable.width = " + turntable.getWidth());
            arcRadius = mWidth / 2.0f;// �뾶 �൱��Բ�İ뾶(Сͼ����Բ�ĵľ���)
            for (int i = 0; i < resIcons.length; i++) {
                FunctionIcon fi = new FunctionIcon();
                bTemp = BitmapFactory.decodeResource(getResources(),
                        resIcons[i]);
                fi.icon = Bitmap.createBitmap(bTemp, 0, 0,
                        (int) (bTemp.getWidth()),
                        (int) (bTemp.getHeight()),
                        m, true);
                fi._icon = Bitmap.createBitmap(bTemp, 0, 0,
                        (int) (bTemp.getWidth()),
                        (int) (bTemp.getHeight()),
                        m, true);
                bTemp.recycle();
//                fi.icon = BitmapCreate.bitmapFromResource(getResources(), resIcons[i], (int) ((float)180 * scale), (int) ((float)180 * scale));
//                fi._icon = BitmapCreate.bitmapFromResource(getResources(), res_Icons[i], (int) ((float)180 * scale), (int) ((float)180 * scale));
                fi.click = false;
                LogUtil.d("icon.width = " + fi.icon.getWidth());
                float intersctAngle = (float) Math.atan2(fi.icon.getWidth() / 2, arcRadius);
                //Log.d("onSizeChanged", "intersctAngle " + i + " = " + intersctAngle);
                fi.mindegree = Angle60Degree / 2 * (2 * i - 1); //�ֽ���
                if (fi.mindegree < 0) {
                    fi.mindegree += Math.PI * 2;
                }

                fi.translateDegree = (float) Angle60Degree * i - intersctAngle;
                fi.rotateDegree = (float) Angle60Degree * i;
                fiList.add(fi);
            }
            /**
             * Math.pow(x,y)��x��y�η� Math.sqrt(x)��ƽ����
             */
            iconRadius = (float) Math.sqrt(Math.pow(arcRadius, 2)
                    + Math.pow(fiList.get(0).icon.getWidth() / 2, 2));
            getLocationInWindow(locationOnScreen);
            rotateTask.run();
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {

        // ƽ�ƣ�x,y�������ص�λ
        nXoffset = canvas.getWidth() / 2;
        nYoffset = canvas.getHeight() / 2;
        //Log.d("RotateFlower.onDraw", "nXoffset = " + nXoffset + "nYoffset = " + nYoffset);
        //�ƶ��滭ԭ��λ��
        //Log.d("onDraw", "heart : " + (nXoffset - turntable.getWidth()/2) + "; " + (nYoffset - turntable.getHeight()/2));
        canvas.save();
        canvas.translate(nXoffset - turntable.getWidth() / 2, nYoffset - turntable.getHeight() / 2);
        // �����ģ�srcΪ��Ҫ����bitmap������dstΪ��Ҫ��ʾ����Ļ�ϵ����򣬣�
        canvas.drawBitmap(turntable, new Rect(0, 0, turntable.getWidth(),
                turntable.getHeight()), new Rect(0, 0, turntable.getWidth(),
                turntable.getWidth()), paint);
        canvas.restore();
        // �ƶ�ԭ�㵽Բ��
        canvas.translate(nXoffset, nYoffset);
        // ������ͼ��
        for (int i = 0; i < fiList.size(); i++) {
            //Log.d("onDraw", i + ".x = " + (iconRadius * Math.sin(fiList.get(i).translateDegree)) + "; y=" + (iconRadius * Math.cos(fiList.get(i).translateDegree)));
            matrixFloat[0] = (float) Math.cos(fiList.get(i).rotateDegree);
            //matrixFloat[0] = 1;
            //matrixFloat[1] = 0;
            matrixFloat[1] = (float) -Math.sin(fiList.get(i).rotateDegree);
            matrixFloat[2] = (float) (iconRadius * Math.sin(fiList.get(i).translateDegree));
            //matrixFloat[2] = -175;
            matrixFloat[3] = (float) Math.sin(fiList.get(i).rotateDegree);
            matrixFloat[4] = (float) Math.cos(fiList.get(i).rotateDegree);
            //matrixFloat[3] = 0;
            //matrixFloat[4] = 1;
            matrixFloat[5] = -(float) (iconRadius * Math.cos(fiList.get(i).translateDegree));
            //matrixFloat[5] = -540;
            matrixFloat[6] = 0;
            matrixFloat[7] = 0;
            matrixFloat[8] = 1f;
            matrix.setValues(matrixFloat);

            if (fiList.get(i).click) {
                // �ѵ����ͼƬ����ȥ
                canvas.drawBitmap(fiList.get(i)._icon, matrix, paint);
                fiList.get(i).click = false;
            } else {
                // ��û�����ͼƬ����ȥ
                canvas.drawBitmap(fiList.get(i).icon, matrix, paint);
            }
            super.onDraw(canvas);
        }
    }


    /**
     * �Ƿ�����ת̨����
     *
     * @param x
     * @param y
     * @return
     */
    private boolean inTurnTable(float x, float y) {
        // ��Բ�����
        double outCircle = Math.PI * arcRadius * arcRadius;
        double inCircle = Math.PI * Math.pow((arcRadius - fiList.get(0).icon.getHeight()), 2);
        double fingerCircle = Math.PI * (x * x + y * y);
        if (fingerCircle < outCircle && fingerCircle > inCircle) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * �Ƿ���Բ���ĵ�����
     *
     * @param x
     * @param y
     * @return
     */
    private boolean inCenterArc(float x, float y) {
        // СԲ�����
        double inCircle = Math.PI * Math.pow((arcRadius - fiList.get(0).icon.getHeight()), 2);
        double fingerCircle = Math.PI * (x * x + y * y);
        if (fingerCircle < inCircle) {
            return true;
        } else {
            return false;
        }
    }

    /**
     *
     */
    class FunctionIcon {
        /**
         * Ĭ��״̬ͼ��
         */
        public Bitmap icon;
        /**
         * ����ʱ״̬ͼ��
         */
        public Bitmap _icon;
        /**
         * �Ƿ���
         */
        public boolean click;
        /**
         * �������С������Ϊ�ֽ���
         */
        public double mindegree;
        /**
         * icon ת�����
         */
        public double translateDegree;
        /**
         * icon ��ת�Ƕ�
         */
        public float rotateDegree;
        /**
         * ��Ӧ�� activity
         */
        @SuppressWarnings({"rawtypes"})
        public Class activity;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX() - nXoffset;
        // float x = event.getX() - mWidth / 2-30;//ccy
        float y = event.getY() - nYoffset;
        y = -y;
//		Log.d("onTouchEvent", "x = " + x + "; y = " + y);
        /**
         * �Ƿ��ڿ���̨
         */
        boolean downInTurnTable = inTurnTable(x, y);
        /**
         * �Ƿ�������Ԫ��
         */
        boolean downInCenterAre = inCenterArc(x, y);
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                touchInTurnTable = downInTurnTable;
                touchInCenterAre = downInCenterAre;
                _touchDegreeFromX = touchDegreeFromX = Math.atan2(x, y);
                moveDegreeFromX = 0;
                break;
            case MotionEvent.ACTION_MOVE:
                if (touchInTurnTable && downInTurnTable) { // ������
                    rotateTask.pause();
                    turnDegree = Math.atan2(x, y) - touchDegreeFromX;
                    touchDegreeFromX += turnDegree; // �µ��ƶ��н�
                    moveDegreeFromX += Math.abs(turnDegree);
                    rotate(turnDegree);
                }
                // ˢ�½���
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                if (touchInTurnTable
                        && downInTurnTable
                        && Math.abs(Math.atan2(x, y) - _touchDegreeFromX) < Math.PI / 6) {
                    if (touchDegreeFromX < 0)
                        touchDegreeFromX += 2 * Math.PI;
                    for (int i = 0; i < 6; i++) {
                        double initAngle = fiList.get(i).mindegree;
                        double endAngle = fiList.get((i + 1) % 6).mindegree;
                        if (initAngle > endAngle) {
                            if (touchDegreeFromX < endAngle) {
                                touchDegreeFromX += Math.PI * 2;
                            }
                            endAngle += Math.PI * 2;
                        }
                        if (initAngle < touchDegreeFromX && touchDegreeFromX < endAngle && moveDegreeFromX < (endAngle - initAngle)/2) {
                            fiList.get(i).click = true;
                            onClickListener.onLeavesClicked(i);
                            invalidate();
                        }
                    }
                }
                if (touchInCenterAre && downInCenterAre) {
                    onClickListener.onHeartClicked();
                }
                if (touchInTurnTable) {
                    touchInTurnTable = false;
                }
                if (touchInCenterAre) {
                    touchInCenterAre = false;
                }

                rotateTask.resume();

                break;
        }
        return true;
    }

    public void setOnClickListener(OnClickListener onClickListener) {
        this.onClickListener = onClickListener;
    }

    public void rotate(double angle) {
        for (FunctionIcon fi : fiList) {
            if (angle > 0) {
                fi.mindegree = fi.mindegree + angle > 2 * Math.PI ? fi.mindegree
                        + angle - 2 * Math.PI
                        : fi.mindegree + angle;
                fi.translateDegree = fi.translateDegree + angle > 2 * Math.PI ? fi.translateDegree
                        + angle - 2 * Math.PI
                        : fi.translateDegree + angle;
                fi.rotateDegree = (float) (fi.rotateDegree + angle > 2 * Math.PI ? fi.rotateDegree
                        + angle - 2 * Math.PI
                        : fi.rotateDegree + angle);
            } else {
                fi.mindegree = fi.mindegree + angle < 0 ? fi.mindegree
                        + angle + 2 * Math.PI
                        : fi.mindegree + angle;
                fi.translateDegree = fi.translateDegree + angle < 0 ? fi.translateDegree
                        + angle + 2 * Math.PI
                        : fi.translateDegree + angle;
                fi.rotateDegree = (float) (fi.rotateDegree + angle < 0 ? fi.rotateDegree
                        + angle + 2 * Math.PI
                        : fi.rotateDegree + angle);
            }
        }
        invalidate();
    }

    public void restartRotate() {
        //Log.d("RotateTask.restartRotate", "restartRotate");
        if (rotateTask.isCancelled()) {
            rotateTask = new RotateTask();
            rotateTask.execute();
        }
    }

    public void pauseRotate(){
        if (rotateTask != null && rotateTask.isRunning()) {
            rotateTask.pause();
        }
    }

    public void resumeRotate(){
        if (rotateTask != null) {
            if(rotateTask.isCancelled()){
                rotateTask = new RotateTask();
                rotateTask.execute();
            } else if(!rotateTask.isRunning()){
                rotateTask.resume();
            }
        }
    }

    /**
     * ����¼�����ӿ�
     */
    public interface OnClickListener {

        /**
         * ���Ĳ��ֱ����
         */
        public void onHeartClicked();

        /**
         * ���Ĳ��ֱ����
         *
         * @param index ������Ļ���id
         */
        public void onLeavesClicked(int index);
    }

    private class RotateTask extends AsyncTask<Integer, Integer, Void> {

        public boolean run = true;
        public boolean pause = true;
        private final int interval = 15;
        private final int angle = 25;

        @Override
        protected void onPreExecute() {
            //Log.d("RotateTask.onPreExecute", "onPreExecute");
            super.onPreExecute();
        }

        @Override
        protected Void doInBackground(Integer... params) {
            while (run) {
                //Log.d("RotateTask.doInBackground", "doInBackground");
                if (!pause) {
                    this.publishProgress();
                    try {
                        Thread.sleep(interval);
                    } catch (InterruptedException e) {
                        onCancelled();
                        e.printStackTrace();
                    }
                }
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            //Log.d("RotateTask.onProgressUpdate", "onProgressUpdate");
            double radian = (double) angle / 180 * Math.PI / (1000 / interval);
            rotate(radian);
        }

        @Override
        protected void onPostExecute(Void result) {

        }

        @Override
        protected void onCancelled() {
            //Log.d("RotateTask.onCancelled", "onCancelled");
            run = false;
            super.onCancelled();
        }

        protected void run() {
            //Log.d("RotateTask", "run");
            this.pause = false;
        }

        protected void pause() {
            //Log.d("RotateTask", "pause");
            this.pause = true;
        }

        protected void resume() {
            //Log.d("RotateTask", "resume");
            this.pause = false;
        }

        protected void stop() {
            //Log.d("RotateTask", "stop");
            this.run = false;
        }

        protected boolean isRunning() {
            //Log.d("RotateTask", "isRunning");
            return this.run;
        }
    }

    public void cancelRotate() {
        //Log.d("RotateTask.cancelRotate", "cancel");
        if (rotateTask != null) {
            rotateTask.cancel(true);
        }
    }
}